{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 第四周作业：对活动进行聚类\n",
    "数据来源于Kaggle竞赛：Event Recommendation Engine Challenge，根据   \n",
    "events they’ve responded to in the past   \n",
    "user demographic information   \n",
    "what events they’ve seen and clicked on in our app   \n",
    "预测用户对某个事件是否感兴趣   \n",
    "\n",
    "共六个数据集：   \n",
    "&emsp; train.csv / test.csv  训练/测试数据    \n",
    "&emsp; users.csv  用户数据   \n",
    "&emsp; events.csv  活动数据    \n",
    "&emsp; event_attendees.csv  活动参加者    \n",
    "&emsp; user_friends.csv  用户好友 "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 0. 导入工具包"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "import datetime  #处理事件字符串\n",
    "from collections import defaultdict\n",
    "from sklearn.cluster import MiniBatchKMeans\n",
    "from sklearn import metrics\n",
    "\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 观察数据"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.1 训练数据 train.csv\n",
    "train.csv 有6列：   \n",
    "&emsp; user：用户ID   \n",
    "&emsp; event：活动ID   \n",
    "&emsp; invited：是否被邀请（0/1）   \n",
    "&emsp; timestamp：ISO-8601 UTC格式时间字符串，表示用户看到该活动的时间   \n",
    "&emsp; interested：0/1   \n",
    "&emsp; not_interested：0/1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>user</th>\n",
       "      <th>event</th>\n",
       "      <th>invited</th>\n",
       "      <th>timestamp</th>\n",
       "      <th>interested</th>\n",
       "      <th>not_interested</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>3044012</td>\n",
       "      <td>1918771225</td>\n",
       "      <td>0</td>\n",
       "      <td>2012-10-02 15:53:05.754000+00:00</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>3044012</td>\n",
       "      <td>1502284248</td>\n",
       "      <td>0</td>\n",
       "      <td>2012-10-02 15:53:05.754000+00:00</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3044012</td>\n",
       "      <td>2529072432</td>\n",
       "      <td>0</td>\n",
       "      <td>2012-10-02 15:53:05.754000+00:00</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3044012</td>\n",
       "      <td>3072478280</td>\n",
       "      <td>0</td>\n",
       "      <td>2012-10-02 15:53:05.754000+00:00</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>3044012</td>\n",
       "      <td>1390707377</td>\n",
       "      <td>0</td>\n",
       "      <td>2012-10-02 15:53:05.754000+00:00</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      user       event  invited                         timestamp  interested  \\\n",
       "0  3044012  1918771225        0  2012-10-02 15:53:05.754000+00:00           0   \n",
       "1  3044012  1502284248        0  2012-10-02 15:53:05.754000+00:00           0   \n",
       "2  3044012  2529072432        0  2012-10-02 15:53:05.754000+00:00           1   \n",
       "3  3044012  3072478280        0  2012-10-02 15:53:05.754000+00:00           0   \n",
       "4  3044012  1390707377        0  2012-10-02 15:53:05.754000+00:00           0   \n",
       "\n",
       "   not_interested  \n",
       "0               0  \n",
       "1               0  \n",
       "2               0  \n",
       "3               0  \n",
       "4               0  "
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 读入数据\n",
    "train = pd.read_csv(\"./homework4_作业说明/train.csv\")\n",
    "train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 15398 entries, 0 to 15397\n",
      "Data columns (total 6 columns):\n",
      "user              15398 non-null int64\n",
      "event             15398 non-null int64\n",
      "invited           15398 non-null int64\n",
      "timestamp         15398 non-null object\n",
      "interested        15398 non-null int64\n",
      "not_interested    15398 non-null int64\n",
      "dtypes: int64(5), object(1)\n",
      "memory usage: 721.9+ KB\n"
     ]
    }
   ],
   "source": [
    "train.info() # 没有缺失值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.2  测试数据 test.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>user</th>\n",
       "      <th>event</th>\n",
       "      <th>invited</th>\n",
       "      <th>timestamp</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1776192</td>\n",
       "      <td>2877501688</td>\n",
       "      <td>0</td>\n",
       "      <td>2012-11-30 11:39:01.230000+00:00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1776192</td>\n",
       "      <td>3025444328</td>\n",
       "      <td>0</td>\n",
       "      <td>2012-11-30 11:39:01.230000+00:00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1776192</td>\n",
       "      <td>4078218285</td>\n",
       "      <td>0</td>\n",
       "      <td>2012-11-30 11:39:01.230000+00:00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1776192</td>\n",
       "      <td>1024025121</td>\n",
       "      <td>0</td>\n",
       "      <td>2012-11-30 11:39:01.230000+00:00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1776192</td>\n",
       "      <td>2972428928</td>\n",
       "      <td>0</td>\n",
       "      <td>2012-11-30 11:39:21.985000+00:00</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      user       event  invited                         timestamp\n",
       "0  1776192  2877501688        0  2012-11-30 11:39:01.230000+00:00\n",
       "1  1776192  3025444328        0  2012-11-30 11:39:01.230000+00:00\n",
       "2  1776192  4078218285        0  2012-11-30 11:39:01.230000+00:00\n",
       "3  1776192  1024025121        0  2012-11-30 11:39:01.230000+00:00\n",
       "4  1776192  2972428928        0  2012-11-30 11:39:21.985000+00:00"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Test.csv 除了没有interested, and not_interested，其余列与train相同\n",
    "test = pd.read_csv(\"./homework4_作业说明/test.csv\")\n",
    "test.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 10237 entries, 0 to 10236\n",
      "Data columns (total 4 columns):\n",
      "user         10237 non-null int64\n",
      "event        10237 non-null int64\n",
      "invited      10237 non-null int64\n",
      "timestamp    10237 non-null object\n",
      "dtypes: int64(3), object(1)\n",
      "memory usage: 320.0+ KB\n"
     ]
    }
   ],
   "source": [
    "test.info() # 没有缺失值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.3 用户数据 users.csv\n",
    "用户描述信息：共7维特征   \n",
    "&emsp; user_id  \n",
    "&emsp; locale：地区，语言   \n",
    "&emsp; birthyear：出生年   \n",
    "&emsp; gender：性别   \n",
    "&emsp; joinedAt：用户加入APP的时间，ISO-8601 UTC time   \n",
    "&emsp; location：地点   \n",
    "&emsp; timezone：时区"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>user_id</th>\n",
       "      <th>locale</th>\n",
       "      <th>birthyear</th>\n",
       "      <th>gender</th>\n",
       "      <th>joinedAt</th>\n",
       "      <th>location</th>\n",
       "      <th>timezone</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>3197468391</td>\n",
       "      <td>id_ID</td>\n",
       "      <td>1993</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-10-02T06:40:55.524Z</td>\n",
       "      <td>Medan  Indonesia</td>\n",
       "      <td>480.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>3537982273</td>\n",
       "      <td>id_ID</td>\n",
       "      <td>1992</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-09-29T18:03:12.111Z</td>\n",
       "      <td>Medan  Indonesia</td>\n",
       "      <td>420.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>823183725</td>\n",
       "      <td>en_US</td>\n",
       "      <td>1975</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-10-06T03:14:07.149Z</td>\n",
       "      <td>Stratford  Ontario</td>\n",
       "      <td>-240.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1872223848</td>\n",
       "      <td>en_US</td>\n",
       "      <td>1991</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-11-04T08:59:43.783Z</td>\n",
       "      <td>Tehran  Iran</td>\n",
       "      <td>210.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>3429017717</td>\n",
       "      <td>id_ID</td>\n",
       "      <td>1995</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-09-10T16:06:53.132Z</td>\n",
       "      <td>NaN</td>\n",
       "      <td>420.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      user_id locale birthyear  gender                  joinedAt  \\\n",
       "0  3197468391  id_ID      1993    male  2012-10-02T06:40:55.524Z   \n",
       "1  3537982273  id_ID      1992    male  2012-09-29T18:03:12.111Z   \n",
       "2   823183725  en_US      1975    male  2012-10-06T03:14:07.149Z   \n",
       "3  1872223848  en_US      1991  female  2012-11-04T08:59:43.783Z   \n",
       "4  3429017717  id_ID      1995  female  2012-09-10T16:06:53.132Z   \n",
       "\n",
       "             location  timezone  \n",
       "0    Medan  Indonesia     480.0  \n",
       "1    Medan  Indonesia     420.0  \n",
       "2  Stratford  Ontario    -240.0  \n",
       "3        Tehran  Iran     210.0  \n",
       "4                 NaN     420.0  "
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#读取数据\n",
    "users = pd.read_csv(\"./homework4_作业说明/users.csv\")\n",
    "users.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 38209 entries, 0 to 38208\n",
      "Data columns (total 7 columns):\n",
      "user_id      38209 non-null int64\n",
      "locale       38209 non-null object\n",
      "birthyear    38209 non-null object\n",
      "gender       38100 non-null object\n",
      "joinedAt     38152 non-null object\n",
      "location     32745 non-null object\n",
      "timezone     37773 non-null float64\n",
      "dtypes: float64(1), int64(1), object(5)\n",
      "memory usage: 2.0+ MB\n"
     ]
    }
   ],
   "source": [
    "users.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "location，timezone，gender，joinedAt 有缺失值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.4 活动数据 events.csv\n",
    "活动描述信息：共110维特征   \n",
    "&emsp; 前9列：event_id, user_id, start_time, city, state, zip, country, lat, and lng.   \n",
    "&emsp; event_id：活动id    \n",
    "&emsp; user_id：参加活动的用户id     \n",
    "&emsp; city, state, zip, and country： more details about the location of the venue (if known).   \n",
    "&emsp; lat and lng： floats（latitude and longitude coordinates of the venue）   \n",
    "&emsp; start_time： 字符串，ISO-8601 UTC time，表示活动开始时间   \n",
    "\n",
    "后101列为词频：count_1, count_2, ..., count_100，count_other   \n",
    "&emsp; count_N：活动描述出现第N个词的次数   \n",
    "&emsp; count_other：除了最常用的100个词之外的其余词出现的次数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>event_id</th>\n",
       "      <th>user_id</th>\n",
       "      <th>start_time</th>\n",
       "      <th>city</th>\n",
       "      <th>state</th>\n",
       "      <th>zip</th>\n",
       "      <th>country</th>\n",
       "      <th>lat</th>\n",
       "      <th>lng</th>\n",
       "      <th>c_1</th>\n",
       "      <th>...</th>\n",
       "      <th>c_92</th>\n",
       "      <th>c_93</th>\n",
       "      <th>c_94</th>\n",
       "      <th>c_95</th>\n",
       "      <th>c_96</th>\n",
       "      <th>c_97</th>\n",
       "      <th>c_98</th>\n",
       "      <th>c_99</th>\n",
       "      <th>c_100</th>\n",
       "      <th>c_other</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>684921758</td>\n",
       "      <td>3647864012</td>\n",
       "      <td>2012-10-31T00:00:00.001Z</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>244999119</td>\n",
       "      <td>3476440521</td>\n",
       "      <td>2012-11-03T00:00:00.001Z</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3928440935</td>\n",
       "      <td>517514445</td>\n",
       "      <td>2012-11-05T00:00:00.001Z</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2582345152</td>\n",
       "      <td>781585781</td>\n",
       "      <td>2012-10-30T00:00:00.001Z</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1051165850</td>\n",
       "      <td>1016098580</td>\n",
       "      <td>2012-09-27T00:00:00.001Z</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 110 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "     event_id     user_id                start_time city state  zip country  \\\n",
       "0   684921758  3647864012  2012-10-31T00:00:00.001Z  NaN   NaN  NaN     NaN   \n",
       "1   244999119  3476440521  2012-11-03T00:00:00.001Z  NaN   NaN  NaN     NaN   \n",
       "2  3928440935   517514445  2012-11-05T00:00:00.001Z  NaN   NaN  NaN     NaN   \n",
       "3  2582345152   781585781  2012-10-30T00:00:00.001Z  NaN   NaN  NaN     NaN   \n",
       "4  1051165850  1016098580  2012-09-27T00:00:00.001Z  NaN   NaN  NaN     NaN   \n",
       "\n",
       "   lat  lng  c_1   ...     c_92  c_93  c_94  c_95  c_96  c_97  c_98  c_99  \\\n",
       "0  NaN  NaN    2   ...        0     1     0     0     0     0     0     0   \n",
       "1  NaN  NaN    2   ...        0     0     0     0     0     0     0     0   \n",
       "2  NaN  NaN    0   ...        0     0     0     0     0     0     0     0   \n",
       "3  NaN  NaN    1   ...        0     0     0     0     0     0     0     0   \n",
       "4  NaN  NaN    1   ...        0     0     0     0     0     0     0     0   \n",
       "\n",
       "   c_100  c_other  \n",
       "0      0        9  \n",
       "1      0        7  \n",
       "2      0       12  \n",
       "3      0        8  \n",
       "4      0        9  \n",
       "\n",
       "[5 rows x 110 columns]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#读取数据\n",
    "events = pd.read_csv(\"./homework4_作业说明/events.csv\")\n",
    "events.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 3137972 entries, 0 to 3137971\n",
      "Columns: 110 entries, event_id to c_other\n",
      "dtypes: float64(2), int64(103), object(5)\n",
      "memory usage: 2.6+ GB\n"
     ]
    }
   ],
   "source": [
    "events.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "数据量太大，之后用io读入"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.5 活动参加者 event_attendees.csv\n",
    "活动参加者：共5维特征   \n",
    "&emsp; event_id：活动ID   \n",
    "&emsp; yes, maybe, invited, and no：以空格隔开的用户列表,分别表示该活动参加的用户、可能参加的用户，被邀请的用户和不参加的用户."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>event</th>\n",
       "      <th>yes</th>\n",
       "      <th>maybe</th>\n",
       "      <th>invited</th>\n",
       "      <th>no</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1159822043</td>\n",
       "      <td>1975964455 252302513 4226086795 3805886383 142...</td>\n",
       "      <td>2733420590 517546982 1350834692 532087573 5831...</td>\n",
       "      <td>1723091036 3795873583 4109144917 3560622906 31...</td>\n",
       "      <td>3575574655 1077296663</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>686467261</td>\n",
       "      <td>2394228942 2686116898 1056558062 3792942231 41...</td>\n",
       "      <td>1498184352 645689144 3770076778 331335845 4239...</td>\n",
       "      <td>1788073374 733302094 1830571649 676508092 7081...</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1186208412</td>\n",
       "      <td>NaN</td>\n",
       "      <td>3320380166 3810793697</td>\n",
       "      <td>1379121209 440668682</td>\n",
       "      <td>1728988561 2950720854</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2621578336</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>855842686</td>\n",
       "      <td>2406118796 3550897984 294255260 1125817077 109...</td>\n",
       "      <td>2671721559 1761448345 2356975806 2666669465 10...</td>\n",
       "      <td>1518670705 880919237 2326414227 2673818347 332...</td>\n",
       "      <td>3500235232</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        event                                                yes  \\\n",
       "0  1159822043  1975964455 252302513 4226086795 3805886383 142...   \n",
       "1   686467261  2394228942 2686116898 1056558062 3792942231 41...   \n",
       "2  1186208412                                                NaN   \n",
       "3  2621578336                                                NaN   \n",
       "4   855842686  2406118796 3550897984 294255260 1125817077 109...   \n",
       "\n",
       "                                               maybe  \\\n",
       "0  2733420590 517546982 1350834692 532087573 5831...   \n",
       "1  1498184352 645689144 3770076778 331335845 4239...   \n",
       "2                              3320380166 3810793697   \n",
       "3                                                NaN   \n",
       "4  2671721559 1761448345 2356975806 2666669465 10...   \n",
       "\n",
       "                                             invited                     no  \n",
       "0  1723091036 3795873583 4109144917 3560622906 31...  3575574655 1077296663  \n",
       "1  1788073374 733302094 1830571649 676508092 7081...                    NaN  \n",
       "2                               1379121209 440668682  1728988561 2950720854  \n",
       "3                                                NaN                    NaN  \n",
       "4  1518670705 880919237 2326414227 2673818347 332...             3500235232  "
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#读取数据\n",
    "event_attendees = pd.read_csv(\"./homework4_作业说明/event_attendees.csv\")\n",
    "event_attendees.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 24144 entries, 0 to 24143\n",
      "Data columns (total 5 columns):\n",
      "event      24144 non-null int64\n",
      "yes        22160 non-null object\n",
      "maybe      20977 non-null object\n",
      "invited    22322 non-null object\n",
      "no         17485 non-null object\n",
      "dtypes: int64(1), object(4)\n",
      "memory usage: 943.2+ KB\n"
     ]
    }
   ],
   "source": [
    "event_attendees.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "缺失值多"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.6 用户好友 user_friends.csv\n",
    "用户好友文件：共2维特征  \n",
    "&emsp; user：用户ID   \n",
    "&emsp; friends：以空格隔开的用户好友ID列表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>user</th>\n",
       "      <th>friends</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>3197468391</td>\n",
       "      <td>1346449342 3873244116 4226080662 1222907620 54...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>3537982273</td>\n",
       "      <td>1491560444 395798035 2036380346 899375619 3534...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>823183725</td>\n",
       "      <td>1484954627 1950387873 1652977611 4185960823 42...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1872223848</td>\n",
       "      <td>83361640 723814682 557944478 1724049724 253059...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>3429017717</td>\n",
       "      <td>4253303705 2130310957 1838389374 3928735761 71...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         user                                            friends\n",
       "0  3197468391  1346449342 3873244116 4226080662 1222907620 54...\n",
       "1  3537982273  1491560444 395798035 2036380346 899375619 3534...\n",
       "2   823183725  1484954627 1950387873 1652977611 4185960823 42...\n",
       "3  1872223848  83361640 723814682 557944478 1724049724 253059...\n",
       "4  3429017717  4253303705 2130310957 1838389374 3928735761 71..."
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#读取数据\n",
    "user_friends = pd.read_csv(\"./homework4_作业说明/user_friends.csv\")\n",
    "user_friends.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 38202 entries, 0 to 38201\n",
      "Data columns (total 2 columns):\n",
      "user       38202 non-null int64\n",
      "friends    38063 non-null object\n",
      "dtypes: int64(1), object(1)\n",
      "memory usage: 597.0+ KB\n"
     ]
    }
   ],
   "source": [
    "user_friends.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "好友列表有缺失值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 处理数据\n",
    "总体活动的数目太多（300w+记录），只对训练集train.csv和测试集test.cv出现的活动（13418条记录）聚类\n",
    "\n",
    "设定变量：  \n",
    "uniqueUsers      &emsp; 独立用户（set）  \n",
    "uniqueEvents     &emsp; 独立活动（set）  \n",
    "userEventScores  &emsp; 用户活动关系矩阵（n_uniqueUsers * n_uniqueEvents）  \n",
    "userIndex        &emsp; 用户index（dict）  \n",
    "eventIndex       &emsp; 活动index（dict）  \n",
    "eventsForUser    &emsp; 每个用户参加的活动（defaultdict(set) ）  \n",
    "usersForEvent    &emsp; 每个活动的参加用户（defaultdict(set) ）  \n",
    "uniqueUserPairs  &emsp; 每个活动的参加者pair（set）  \n",
    "uniqueEventPairs &emsp; 每个用户所参加活动pair（set）  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1 统计训练集和测试集中出现的活动"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "uniqueEvents :13418\n"
     ]
    }
   ],
   "source": [
    "data_path = './homework4_作业说明/'\n",
    "# 统计训练集中有多少不同的用户的events\n",
    "uniqueEvents = set()\n",
    "usersForEvent = defaultdict(set)\n",
    "    \n",
    "for filename in [data_path + \"train.csv\", data_path + \"test.csv\"]:\n",
    "    f = open(filename, 'r')\n",
    "    \n",
    "    # 跳过第一行header\n",
    "    f.readline().strip().split(\",\")\n",
    "    \n",
    "    for line in f:    # 逐行读入\n",
    "        cols = line.strip().split(\",\")  # 每行数据按逗号分开\n",
    "        uniqueEvents.add(cols[1])   #第二列为活动ID\n",
    "        usersForEvent[cols[1]].add(cols[0])    #该活动被用户参加\n",
    "\n",
    "f.close()\n",
    "\n",
    "n_uniqueEvents = len(uniqueEvents)  # 活动数量\n",
    "\n",
    "print(\"uniqueEvents :%d\" % n_uniqueEvents)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "Int64Index: 13418 entries, 0 to 3137701\n",
      "Columns: 110 entries, event_id to c_other\n",
      "dtypes: float64(2), int64(103), object(5)\n",
      "memory usage: 11.4+ MB\n"
     ]
    }
   ],
   "source": [
    "# 抽出uniqueEvents对应的events数据集里的数据，并存为csv文件\n",
    "unique_events = events.loc[events['event_id'].isin(uniqueEvents)]\n",
    "unique_events.to_csv('unique_events.csv')\n",
    "unique_events.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "用户和活动数量大幅减少"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2 对选取的events数据进行处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>start_time</th>\n",
       "      <th>city</th>\n",
       "      <th>state</th>\n",
       "      <th>zip</th>\n",
       "      <th>country</th>\n",
       "      <th>lat</th>\n",
       "      <th>lng</th>\n",
       "      <th>c_1</th>\n",
       "      <th>c_2</th>\n",
       "      <th>c_3</th>\n",
       "      <th>...</th>\n",
       "      <th>c_92</th>\n",
       "      <th>c_93</th>\n",
       "      <th>c_94</th>\n",
       "      <th>c_95</th>\n",
       "      <th>c_96</th>\n",
       "      <th>c_97</th>\n",
       "      <th>c_98</th>\n",
       "      <th>c_99</th>\n",
       "      <th>c_100</th>\n",
       "      <th>c_other</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2012-10-31T00:00:00.001Z</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2012-11-03T00:00:00.001Z</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2012-11-05T00:00:00.001Z</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2012-10-30T00:00:00.001Z</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2012-09-27T00:00:00.001Z</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 108 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                 start_time  city  state  zip  country  lat  lng  c_1  c_2  \\\n",
       "0  2012-10-31T00:00:00.001Z     0      0    0        0  0.0  0.0    2    0   \n",
       "1  2012-11-03T00:00:00.001Z     0      0    0        0  0.0  0.0    2    0   \n",
       "2  2012-11-05T00:00:00.001Z     0      0    0        0  0.0  0.0    0    0   \n",
       "3  2012-10-30T00:00:00.001Z     0      0    0        0  0.0  0.0    1    0   \n",
       "4  2012-09-27T00:00:00.001Z     0      0    0        0  0.0  0.0    1    1   \n",
       "\n",
       "   c_3   ...     c_92  c_93  c_94  c_95  c_96  c_97  c_98  c_99  c_100  \\\n",
       "0    2   ...        0     1     0     0     0     0     0     0      0   \n",
       "1    2   ...        0     0     0     0     0     0     0     0      0   \n",
       "2    0   ...        0     0     0     0     0     0     0     0      0   \n",
       "3    2   ...        0     0     0     0     0     0     0     0      0   \n",
       "4    0   ...        0     0     0     0     0     0     0     0      0   \n",
       "\n",
       "   c_other  \n",
       "0        9  \n",
       "1        7  \n",
       "2       12  \n",
       "3        8  \n",
       "4        9  \n",
       "\n",
       "[5 rows x 108 columns]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "from sklearn import preprocessing\n",
    "\n",
    "\n",
    "# 将NaN填为0\n",
    "unique_events[['start_time','city','state','zip','country','lat','lng']] = unique_events[['start_time','city','state','zip','country','lat','lng']].fillna(0)\n",
    "\n",
    "# 活动开始时间：保留年月日\n",
    "def getStartTime(dateString):\n",
    "    start_time = datetime.datetime.strptime(dateString, \"%Y-%m-%dT%H:%M:%S.%fZ\")\n",
    "    return \"\".join([str(start_time.year), str(start_time.month), str(start_time.day)])\n",
    "\n",
    "# \n",
    "label_encoder = preprocessing.LabelEncoder()\n",
    "unique_events['city'] = label_encoder.fit(unique_events['city'].astype(str)).transform(unique_events['city'].astype(str))\n",
    "unique_events['state'] = label_encoder.fit(unique_events['state'].astype(str)).transform(unique_events['state'].astype(str))\n",
    "unique_events['zip'] = label_encoder.fit(unique_events['state'].astype(str)).transform(unique_events['state'].astype(str))\n",
    "unique_events['country'] = label_encoder.fit(unique_events['state'].astype(str)).transform(unique_events['state'].astype(str))\n",
    "\n",
    "\n",
    "# event_id, user_id 不作为聚类的特征\n",
    "unique_events = unique_events.drop(['event_id'], axis=1)\n",
    "unique_events = unique_events.drop(['user_id'], axis=1)\n",
    "\n",
    "unique_events.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 将活动的参加用户数加入数据集\n",
    "#userForEvent_sortList = dict()  # 设定按照独立活动顺序排序的活动参加者字典（活动ID-参加者ID）\n",
    "userForEvent_num = dict()  # 参加活动的用户数量\n",
    "date_list = dict()\n",
    "\n",
    "f = open('unique_events.csv', 'r')\n",
    "# 跳过第一行header\n",
    "f.readline().strip().split(\",\")\n",
    "for line in f:\n",
    "    cols = line.strip().split(\",\")  # 每行数据按逗号分开\n",
    "    date_list[cols[1]] = getStartTime(cols[3])  # 变换时间格式\n",
    "    if cols[1] in list(usersForEvent.keys()):  # 如果event_id在参加活动的用户数据集中\n",
    "        #userForEvent_sortList[cols[1]] = list(usersForEvent[cols[1]]) # 将参加用户加入字典\n",
    "        userForEvent_num[cols[1]] = len(list(usersForEvent[cols[1]])) # 将参加用户数量加入字典\n",
    "        #print(userForEvent_sortList[cols[1]])  # 没有空用户\n",
    "f.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>start_time</th>\n",
       "      <th>city</th>\n",
       "      <th>state</th>\n",
       "      <th>zip</th>\n",
       "      <th>country</th>\n",
       "      <th>lat</th>\n",
       "      <th>lng</th>\n",
       "      <th>c_1</th>\n",
       "      <th>c_2</th>\n",
       "      <th>c_3</th>\n",
       "      <th>...</th>\n",
       "      <th>c_93</th>\n",
       "      <th>c_94</th>\n",
       "      <th>c_95</th>\n",
       "      <th>c_96</th>\n",
       "      <th>c_97</th>\n",
       "      <th>c_98</th>\n",
       "      <th>c_99</th>\n",
       "      <th>c_100</th>\n",
       "      <th>c_other</th>\n",
       "      <th>attend_users_num</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>20121031</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>...</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>9</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2012113</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>7</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2012115</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>12</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>20121030</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>8</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2012927</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>9</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 109 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "  start_time  city  state  zip  country  lat  lng  c_1  c_2  c_3  \\\n",
       "0   20121031     0      0    0        0  0.0  0.0    2    0    2   \n",
       "1    2012113     0      0    0        0  0.0  0.0    2    0    2   \n",
       "2    2012115     0      0    0        0  0.0  0.0    0    0    0   \n",
       "3   20121030     0      0    0        0  0.0  0.0    1    0    2   \n",
       "4    2012927     0      0    0        0  0.0  0.0    1    1    0   \n",
       "\n",
       "         ...         c_93  c_94  c_95  c_96  c_97  c_98  c_99  c_100  c_other  \\\n",
       "0        ...            1     0     0     0     0     0     0      0        9   \n",
       "1        ...            0     0     0     0     0     0     0      0        7   \n",
       "2        ...            0     0     0     0     0     0     0      0       12   \n",
       "3        ...            0     0     0     0     0     0     0      0        8   \n",
       "4        ...            0     0     0     0     0     0     0      0        9   \n",
       "\n",
       "   attend_users_num  \n",
       "0                 1  \n",
       "1                 1  \n",
       "2                 8  \n",
       "3                 1  \n",
       "4                 1  \n",
       "\n",
       "[5 rows x 109 columns]"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将活动的参加用户以及数量加入unique_events\n",
    "#unique_events['attend_users'] = userForEvent_sortList.values()\n",
    "#unique_events = unique_events.drop(['attend_users'], axis=1)\n",
    "\n",
    "unique_events['attend_users_num'] = userForEvent_num.values()\n",
    "unique_events['start_time'] = date_list.values()\n",
    "\n",
    "# 标准化数据\n",
    "ss_data = StandardScaler().fit_transform(unique_events)\n",
    "\n",
    "unique_events.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 聚类 Kmeans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#MiniBatchKMeans方法聚类，并计算CH_score\n",
    "cluster_score = pd.DataFrame()\n",
    "def K_cluster(K, data):\n",
    "    #K-means\n",
    "    mb_kmeans = MiniBatchKMeans(n_clusters = K)\n",
    "    mb_kmeans.fit(data)\n",
    "    \n",
    "    # K值的评估标准:CH_score, 分数值越大则聚类效果越好\n",
    "    CH_score = metrics.calinski_harabaz_score(data, mb_kmeans.predict(data))\n",
    "    cluster_score['cluster_'+ str(K)] = mb_kmeans.predict(data)\n",
    "    print(\"K = {}\".format(K), \",  CH_score:\", CH_score)\n",
    "    return CH_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "K = 10 ,  CH_score: 349.515684749\n",
      "K = 20 ,  CH_score: 179.339613321\n",
      "K = 30 ,  CH_score: 117.578874669\n",
      "K = 40 ,  CH_score: 133.090302607\n",
      "K = 50 ,  CH_score: 88.9042634271\n",
      "K = 60 ,  CH_score: 82.0231383849\n",
      "K = 70 ,  CH_score: 73.1235686902\n",
      "K = 80 ,  CH_score: 70.362340789\n",
      "K = 90 ,  CH_score: 70.2735854944\n",
      "K = 100 ,  CH_score: 73.7383770011\n"
     ]
    }
   ],
   "source": [
    "# K=10，20，…，100\n",
    "Ks_1 = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]\n",
    "CH_scores_1 = []\n",
    "for K in Ks_1:\n",
    "    ch = K_cluster(K, ss_data)\n",
    "    CH_scores_1.append(ch)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>cluster_10</th>\n",
       "      <th>cluster_20</th>\n",
       "      <th>cluster_30</th>\n",
       "      <th>cluster_40</th>\n",
       "      <th>cluster_50</th>\n",
       "      <th>cluster_60</th>\n",
       "      <th>cluster_70</th>\n",
       "      <th>cluster_80</th>\n",
       "      <th>cluster_90</th>\n",
       "      <th>cluster_100</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>7</td>\n",
       "      <td>15</td>\n",
       "      <td>12</td>\n",
       "      <td>9</td>\n",
       "      <td>30</td>\n",
       "      <td>44</td>\n",
       "      <td>16</td>\n",
       "      <td>49</td>\n",
       "      <td>41</td>\n",
       "      <td>16</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>19</td>\n",
       "      <td>0</td>\n",
       "      <td>15</td>\n",
       "      <td>4</td>\n",
       "      <td>47</td>\n",
       "      <td>52</td>\n",
       "      <td>76</td>\n",
       "      <td>41</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2</td>\n",
       "      <td>19</td>\n",
       "      <td>0</td>\n",
       "      <td>15</td>\n",
       "      <td>27</td>\n",
       "      <td>45</td>\n",
       "      <td>31</td>\n",
       "      <td>69</td>\n",
       "      <td>60</td>\n",
       "      <td>66</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>7</td>\n",
       "      <td>15</td>\n",
       "      <td>0</td>\n",
       "      <td>9</td>\n",
       "      <td>30</td>\n",
       "      <td>25</td>\n",
       "      <td>16</td>\n",
       "      <td>7</td>\n",
       "      <td>23</td>\n",
       "      <td>38</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>9</td>\n",
       "      <td>18</td>\n",
       "      <td>29</td>\n",
       "      <td>30</td>\n",
       "      <td>0</td>\n",
       "      <td>47</td>\n",
       "      <td>16</td>\n",
       "      <td>68</td>\n",
       "      <td>38</td>\n",
       "      <td>71</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   cluster_10  cluster_20  cluster_30  cluster_40  cluster_50  cluster_60  \\\n",
       "0           7          15          12           9          30          44   \n",
       "1           2          19           0          15           4          47   \n",
       "2           2          19           0          15          27          45   \n",
       "3           7          15           0           9          30          25   \n",
       "4           9          18          29          30           0          47   \n",
       "\n",
       "   cluster_70  cluster_80  cluster_90  cluster_100  \n",
       "0          16          49          41           16  \n",
       "1          52          76          41            1  \n",
       "2          31          69          60           66  \n",
       "3          16           7          23           38  \n",
       "4          16          68          38           71  "
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cluster_score.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x10ea6c630>]"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x10ebd0a90>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 画图观察结果\n",
    "plt.plot(Ks_1, np.array(CH_scores_1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "k = 10时，效果最好  \n",
    "每次的运行结果不一样？上次的结果显示40时效果更好。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## 4. PCA降维再聚类\n",
    "class sklearn.decomposition.PCA(n_components=None, copy=True, whiten=False, svd_solver=’auto’, tol=0.0, iterated_power=’auto’, random_state=None)  \n",
    "http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html\n",
    "\n",
    "**explained_variance_ratio_**: Percentage of variance explained by each of the selected components（每个成分保留了多少特征）  \n",
    "**singular_values_**: equal to the 2-norms of the n_components variables in the lower-dimensional space（降维后的坐标）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.1 对全部特征降维"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from sklearn.decomposition import PCA\n",
    "\n",
    "# 定义获得成分数的函数\n",
    "def getComponents(components_num, data):\n",
    "    pca = PCA(n_components = components_num)\n",
    "    pca.fit(data)\n",
    "    \n",
    "    #pca_data = pca.transform(data)\n",
    "    #print('explained_variance_ratio_: ', pca.explained_variance_ratio_)  # 每个component保留多少information，重要的指标\n",
    "    #print('singular_values_: ', pca.singular_values_)  \n",
    "    \n",
    "    return pca.explained_variance_ratio_ "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "components number:  10 , sum of variance_ratio_ 0.413318963433\n",
      "components number:  20 , sum of variance_ratio_ 0.518652982489\n",
      "components number:  30 , sum of variance_ratio_ 0.607029032708\n",
      "components number:  40 , sum of variance_ratio_ 0.68641168142\n",
      "components number:  50 , sum of variance_ratio_ 0.756608354646\n",
      "components number:  60 , sum of variance_ratio_ 0.820484106528\n",
      "components number:  70 , sum of variance_ratio_ 0.878887759924\n",
      "components number:  80 , sum of variance_ratio_ 0.929262371609\n",
      "components number:  90 , sum of variance_ratio_ 0.971130369064\n",
      "components number:  100 , sum of variance_ratio_ 0.99734245037\n"
     ]
    }
   ],
   "source": [
    "# 定义 components 范围\n",
    "components_num = np.linspace(10, 100, num = 10)  # float64\n",
    "pca_variance = []\n",
    "pca_variance_sum = dict()\n",
    "\n",
    "# 对每个 component 调用getComponents函数降维\n",
    "for c in components_num:\n",
    "    component = getComponents(int(c), ss_data)\n",
    "    pca_variance.append(component)\n",
    "    pca_variance_sum[int(c)] = component.sum()\n",
    "    print ('components number: ', int(c), ', sum of variance_ratio_', pca_variance_sum[int(c)])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "当components选择65左右时，能保留85%的信息"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "K = 2 ,  CH_score: 1495.94488207\n",
      "K = 4 ,  CH_score: 681.867430088\n",
      "K = 5 ,  CH_score: 735.483990851\n",
      "K = 10 ,  CH_score: 420.335006748\n",
      "K = 20 ,  CH_score: 246.049111963\n",
      "K = 30 ,  CH_score: 205.031090983\n",
      "K = 40 ,  CH_score: 143.426614263\n",
      "K = 50 ,  CH_score: 119.476425313\n",
      "K = 60 ,  CH_score: 102.485865754\n",
      "K = 65 ,  CH_score: 113.218097489\n"
     ]
    }
   ],
   "source": [
    "# component = 65\n",
    "pca_all = PCA(n_components = 65)\n",
    "pca_data_all = pca_all.fit_transform(ss_data)\n",
    "\n",
    "# KMeans聚类，K=10，20，…，65\n",
    "Ks_pca_all = [2, 4, 5, 10, 20, 30, 40, 50, 60, 65]\n",
    "CH_scores_pca1 = []\n",
    "for K in Ks_pca_all:\n",
    "    ch = K_cluster(K, pca_data_all)\n",
    "    CH_scores_pca1.append(ch)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x10e89ce48>]"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nZBKQMW4AAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x10da5dd30>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 画图观察结果\n",
    "plt.plot(Ks_pca_all, np.array(CH_scores_pca1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "结果与降维之前并没有什么区别，依旧是k=10时最好。   \n",
    "也许K范围缩小到0~10之间有区别？（经尝试，没有什么变化）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.2 尝试将后100维词频特征和前9维分开降维"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 前9维和最后一维添加的特征\n",
    "#ss_data_first9 = np.reshape(np.append(ss_data[:, 0:7], ss_data[:, 108]),(-1,8))  array的转换很麻烦\n",
    "\n",
    "ss_data = pd.DataFrame(ss_data, columns = list(unique_events.columns.values))\n",
    "ss_data_first9 = ss_data.iloc[:, 0:7].copy()\n",
    "ss_data_first9['attend_users_num'] = ss_data[['attend_users_num']].copy()\n",
    "\n",
    "# 词频100维\n",
    "ss_data_last100 = ss_data.iloc[:, 7:108].copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "components number for 8 features:  1 , sum of variance_ratio_ 0.538483762455\n",
      "components number for 8 features:  2 , sum of variance_ratio_ 0.666597682782\n",
      "components number for 8 features:  3 , sum of variance_ratio_ 0.788354770373\n",
      "components number for 8 features:  4 , sum of variance_ratio_ 0.892945027236\n",
      "components number for 8 features:  5 , sum of variance_ratio_ 0.963811082096\n",
      "components number for 8 features:  6 , sum of variance_ratio_ 0.993808818869\n",
      "components number for 8 features:  7 , sum of variance_ratio_ 1.0\n",
      "components number for 8 features:  8 , sum of variance_ratio_ 1.0\n"
     ]
    }
   ],
   "source": [
    "# 前9维\n",
    "# 定义 components 范围\n",
    "components_num_first9 = np.linspace(1, 8, num = 8)  # float64\n",
    "pca_variance_first9 = []\n",
    "pca_variance_sum_first9 = dict()\n",
    "\n",
    "# 对每个 component 调用getComponents函数降维\n",
    "for c in components_num_first9:\n",
    "    component_first9 = getComponents(int(c), ss_data_first9)\n",
    "    pca_variance_first9.append(component_first9)\n",
    "    pca_variance_sum_first9[int(c)] = component_first9.sum()\n",
    "    print ('components number for 8 features: ', int(c), ', sum of variance_ratio_', pca_variance_sum_first9[int(c)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "components number for 100 features:  10 , sum of variance_ratio_ 0.414780819586\n",
      "components number for 100 features:  20 , sum of variance_ratio_ 0.524685504138\n",
      "components number for 100 features:  30 , sum of variance_ratio_ 0.618155472652\n",
      "components number for 100 features:  40 , sum of variance_ratio_ 0.699477561754\n",
      "components number for 100 features:  50 , sum of variance_ratio_ 0.774047236763\n",
      "components number for 100 features:  60 , sum of variance_ratio_ 0.840539806222\n",
      "components number for 100 features:  70 , sum of variance_ratio_ 0.899506825482\n",
      "components number for 100 features:  80 , sum of variance_ratio_ 0.950314714554\n",
      "components number for 100 features:  90 , sum of variance_ratio_ 0.988815971045\n",
      "components number for 100 features:  100 , sum of variance_ratio_ 0.999984689007\n"
     ]
    }
   ],
   "source": [
    "# 后100维\n",
    "# 定义 components 范围\n",
    "components_num_last100 = np.linspace(10, 100, num = 10)  # float64\n",
    "pca_variance_last100 = []\n",
    "pca_variance_sum_last100 = dict()\n",
    "\n",
    "# 对每个 component 调用getComponents函数降维\n",
    "for c in components_num_last100:\n",
    "    component_last100 = getComponents(int(c), ss_data_last100)\n",
    "    pca_variance_last100.append(component_last100)\n",
    "    pca_variance_sum_last100[int(c)] = component_last100.sum()\n",
    "    print ('components number for 100 features: ', int(c), ', sum of variance_ratio_', pca_variance_sum_last100[int(c)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(13418, 64)"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 合并分开降维的前9维和后100维\n",
    "pca_first9 = PCA(n_components = 4)\n",
    "pca_data_first9 = pca_first9.fit_transform(ss_data_first9)\n",
    "\n",
    "pca_last100 = PCA(n_components = 60)\n",
    "pca_data_last100 = pca_last100.fit_transform(ss_data_last100)\n",
    "\n",
    "pca_data_new_all = pd.concat([pd.DataFrame(pca_data_first9), pd.DataFrame(pca_data_last100)], axis = 1)\n",
    "pca_data_new_all.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "K = 5 ,  CH_score: 668.946660086\n",
      "K = 10 ,  CH_score: 455.212337498\n",
      "K = 20 ,  CH_score: 239.496356398\n",
      "K = 40 ,  CH_score: 145.087945514\n",
      "K = 60 ,  CH_score: 99.2782455812\n"
     ]
    }
   ],
   "source": [
    "# KMeans聚类\n",
    "Ks_pca_new_all = [5, 10, 20, 40, 60]\n",
    "CH_scores_pca3 = []\n",
    "for K in Ks_pca_new_all:\n",
    "    ch = K_cluster(K, pca_data_new_all)\n",
    "    CH_scores_pca3.append(ch)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "还是k = 10时，评价最好。  \n",
    "降维前后及是否分开降维都对聚类的结果影响不大？\n",
    "\n",
    "\n",
    "疑问：  \n",
    "1. component选择多少合适？是根据最终的模型评价结果再调整？  \n",
    "2. 词频的降维也是用pca比较合适吗？还是有其他的更好的方法？\n",
    "3. 词频降维时是和其他的特征一起比较好，还是分开？"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
